/**
 * H5高性能下拉刷新组件
 * <PullRefresh onRefresh={this.onRefresh} container={'id'}/>
 *
 * 1)H5下拉刷新组件在列表较长时性能上不如native下拉刷新 但是提供了beforePull方法和afterPull方法 这些方法在下拉时都知会执行一次
 * 使用者可以在这些方法里面将不需要的dom隐藏，结束后在显示 最大化优化性能
 */

import './css/pullrefresh.css';

class PullRefresh extends React.PureComponent {
    // static propTypes={
    //     container:React.PropTypes.string, //用于触发滑动事件的容器id，一般为PullRefresh组件的相邻父元素
    //     scrollContainer:React.PropTypes.string, //具有滚动条的容器id，不指定时为document.body，即浏览器窗口；如果是在页面局部容器中下拉刷新则必须指定
    //     dragThreshold:React.PropTypes.number, // 临界值：当拖动多高时触发正在刷新
    //     moveCount:React.PropTypes.number, // 位移系数
    //     beforePull:React.PropTypes.func, // 触发下拉刷新前调用
    //     afterPull:React.PropTypes.number, // 触发下拉刷新后调用  flag：true代表触发了刷新 flag：false代表没有触发下拉刷新只是拉下马又收回去了
    //     onRefresh:React.PropTypes.number // 触发下拉刷新回调 可以用来加载数据
    // };

    static defaultProps = {
        dragThreshold: 0.3,
        moveCount: 200,
        beforePull: function(){},
        afterPull: function(flag){},
        onRefresh: function(){}
    };

    constructor(props){
        super(props);

        this.dragThreshold = this.props.dragThreshold; // 临界值

        this.moveCount = this.props.moveCount; // 位移系数

        this.dragStart = null;// 开始抓取标志位

        this.percentage = 0;// 拖动量的百分比

        this.changeOneTimeFlag = 0;// 修改dom只执行1次标志位

        this.joinRefreshFlag = null;// 进入下拉刷新状态标志位

        this.refreshFlag = 0;// 下拉刷新执行是控制页面假死标志位

        this.state={};

        this.touchStart=this.touchStart.bind(this);
        this.touchMove=this.touchMove.bind(this);
        this.touchEnd=this.touchEnd.bind(this);
    }

    componentDidMount() {
        const {container, scrollContainer} = this.props;

        this.pullIcon = this.refs.pullIcon;

        this.container = document.getElementById(container);

        this.scrollContainer=scrollContainer?document.getElementById(scrollContainer):document.body;

        this.bindEvent();
    }

    touchStart(event){
        if (this.refreshFlag) {
            event.preventDefault();
            return;
        }

        event = event.touches[0];
        this.dragStart = event.clientY;

        this.container.style.webkitTransition = 'none';
        this.pullIcon.classList.add('none');

    }

    touchMove(event){
        if (this.dragStart === null) {
            return;
        }

        if (this.refreshFlag) {
            event.preventDefault();
            return;
        }

        const target = event.touches[0];

        this.percentage = (this.dragStart - target.clientY) / window.screen.height;

        // 当且紧当scrolltop是0且往下滚动时才触发
        if (this.scrollContainer.scrollTop == 0) {
            if (this.percentage < 0) {
                event.preventDefault();
                if (!this.changeOneTimeFlag) {

                    this.props.beforePull();
                    this.changeOneTimeFlag = 1;

                }

                const translateX = -this.percentage*this.moveCount;

                this.joinRefreshFlag = true;

                if (Math.abs(this.percentage) > this.dragThreshold) {

                    this.setState({
                        stateText: '释放刷新'
                    });
                } else {
                    this.setState({
                        stateText: '下拉刷新'
                    });
                }


                if (this.percentage > 0) {

                    this.container.style.webkitTransform = 'translate3d(0,' + translateX + 'px,0)';
                } else {

                    this.container.style.webkitTransform = 'translate3d(0,' + translateX + 'px,0)';
                }
            } else {

                if (this.joinRefreshFlag == null) {
                    this.joinRefreshFlag = false;
                }
            }
        } else {

            if (this.joinRefreshFlag == null) {
                this.joinRefreshFlag = false;
            }
        }

    }

    touchEnd(event){
        if (this.percentage === 0) {
            return;
        }

        if (this.refreshFlag) {
            event.preventDefault();
            return;
        }

        if (Math.abs(this.percentage) > this.dragThreshold && this.joinRefreshFlag) {

            this.props.onRefresh(() => {
                this.setState({
                    stateText: '刷新成功'
                });
                this.pullIcon.classList.add('none');

                this.container.style.webkitTransform = 'translate3d(0,0,0)';

                setTimeout(() => {
                    this.props.afterPull(true);
                    // 重置标志位
                    this.refreshFlag = 0;
                }, 300);
            });

            this.setState({
                stateText: '正在刷新..'
            });
            this.pullIcon.classList.remove('none');

            this.container.style.webkitTransition = '330ms';
            this.container.style.webkitTransform = 'translate3d(0,' + 43 + 'px,0)';

            // 进入下拉刷新状态
            this.refreshFlag = 1;
        } else {

            if (this.joinRefreshFlag) {
                this.refreshFlag = 1;
                this.container.style.webkitTransition = '330ms';
                this.container.style.webkitTransform = 'translate3d(0,0,0)';

                setTimeout(() => {
                    this.props.afterPull();
                    // 重置标志位
                    this.refreshFlag = 0;
                },300);
            }

        }

        // 重置changeOneTimeFlag
        this.changeOneTimeFlag = 0;

        // 重置joinRefreshFlag
        this.joinRefreshFlag = null;

        // 重置percentage
        this.dragStart = null;

        // 重置percentage
        this.percentage = 0;
    }

    bindEvent(){
        const dom = this.container;// 监听touch事件的元素dom
        dom.addEventListener('touchstart', this.touchStart);
        dom.addEventListener('touchmove', this.touchMove);
        dom.addEventListener('touchend', this.touchEnd);
    }

    render() {
        return (
            <div className="pull-down-content">
                <div ref="pullIcon" className="spinner"></div>
                <span>{this.state.stateText}</span>
            </div>
        );
    }
}

export default PullRefresh